Skip to content

refactor: two binaries — amesh (CLI) + amesh-agent (server superset) - #13

Merged
YairEtzion merged 4 commits into
mainfrom
refactor/single-package
Apr 3, 2026
Merged

refactor: two binaries — amesh (CLI) + amesh-agent (server superset)#13
YairEtzion merged 4 commits into
mainfrom
refactor/single-package

Conversation

@YairEtzion

@YairEtzion YairEtzion commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Final package architecture: two separate binaries, two separate npm packages.

amesh (@authmesh/cli) — controller binary:

amesh init / listen / invite / list / revoke / grant / provision / shell

amesh-agent (@authmesh/agent) — server binary (superset of CLI):

amesh-agent init / listen / invite / list / revoke / grant / provision / shell / agent start

Install:

brew install ameshdev/tap/amesh          # laptop (controller)
brew install ameshdev/tap/amesh-agent    # server (target) — includes all CLI commands

Security fixes included

  • C1: Relay challenge-response — agent must sign a random challenge to prove key ownership during registration. Prevents squatting.
  • C2: Bootstrap response whitelist — prevents JSON injection via forwarded messages
  • H1: Single session enforcement — boolean flag, no race conditions
  • B2: PTY output format — was sending raw base64 (broken), now JSON-wrapped
  • M2: Frame type validation — rejects unknown frame types
  • M3: Predictable session OTC — now uses crypto.randomUUID()
  • L3: Idle timeout min bound — enforces minimum 1 minute

Doc updates

  • README: packages table includes @authmesh/agent
  • CLI README: lists all commands including shell/grant
  • CLAUDE.md: CLI description updated
  • ADR-011: reflects final architecture
  • Remote shell guide: two-binary install instructions
  • shell-client.ts: error message says amesh agent start not amesh-agent start
  • Dockerfile.relay: removed ghost shell package reference

After merge

  • npm deprecate @authmesh/shell "Renamed. Use @authmesh/cli (controller) or @authmesh/agent (server)"

Test plan

  • bun run build — 7 packages build (core, keystore, cli, agent, sdk, relay, landpage)
  • CLI tests: 15 pass
  • Agent tests: 15 pass
  • Lint: clean
  • Docker: relay builds and starts, challenge-response verified
  • Landing page prerenders all pages

… start in CLI

One package, one binary, one install:
- amesh shell <device> [-c cmd] — remote shell client (oclif command)
- amesh agent start [--allow-root] [--idle-timeout] — daemon (oclif command)
- All existing commands unchanged

Removed @authmesh/shell package entirely. Shell cipher, handshake, frame,
agent, and shell client code now lives in @authmesh/cli.

15 tests moved from shell package to CLI (shell-cipher: 8, frame: 7).

Updated: ADR-011, landing page guide + use case, grant command text.
All commands now use `amesh` prefix: `amesh shell`, `amesh agent start`.
Security fixes:
- B2: PTY output now wrapped in JSON {type:'data',payload:...} (was raw base64 — broken)
- C2: Bootstrap response whitelist fields (prevent JSON injection)
- M2: Frame parser rejects unknown frame types
- M3: Shell session OTC uses crypto.randomUUID() (was Math.random)
- L3: Idle timeout min bound (min: 1 minute)

Doc fixes:
- shell-client.ts error message: amesh-agent → amesh agent start
- CLAUDE.md: CLI description includes shell/agent/grant
- README.md: CLI package table includes shell/agent/grant
- CLI README: added shell, agent start, grant to commands list
- ADR-011: removed self-contradicting rejected alternative
- Removed ghost packages/agent/ directory
…sion

C1 fix — Agent registration now requires proof of key ownership:
1. Agent sends { type: 'agent', deviceId, publicKey }
2. Relay responds with { type: 'agent_challenge', challenge: randomUUID }
3. Agent signs challenge with private key, sends { type: 'agent_challenge_response', sig }
4. Relay verifies ECDSA-P256 signature against claimed publicKey
5. Only then registers the agent

An attacker who knows the publicKey cannot forge the signature.
Relay imports verifyMessage from @authmesh/core for verification.

H1 fix — Single session enforcement:
- Replaced maxSessions=5 + per-controller tracking with simple boolean flag
- sessionActive set before handshake, cleared in .finally()
- No race condition, no counter leaks, no session cross-contamination

Also: fixed Dockerfile.relay for consolidated workspace (removed shell ref)
Two separate packages, two separate binaries:
- @authmesh/cli (amesh): init, listen, invite, list, revoke, grant, provision, shell
- @authmesh/agent (amesh-agent): superset — all CLI commands + agent daemon

CLI has no daemon code. Agent is a full copy of CLI + agent start command.
~400 lines of shared protocol code duplicated (shell-cipher, handshake, frame).

Updated: README packages table, remote shell guide install section, agent README.
@YairEtzion YairEtzion changed the title refactor: single package — amesh shell + amesh agent start in CLI refactor: two binaries — amesh (CLI) + amesh-agent (server superset) Apr 3, 2026
@YairEtzion
YairEtzion merged commit 25475a8 into main Apr 3, 2026
1 check passed
@YairEtzion
YairEtzion deleted the refactor/single-package branch April 3, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant